<?php

class NCore_PageTest
{
    private $page = NULL;
    private $results = "";
    private $methods = array();
    private $markup = NULL;
    private $pageMarkup = NULL;
    private $failedTestsCount = 0;

    function __construct()
    {
    }

    public function createTestTemplate($page)
    {
        $templateCode = <<<EOD
&lt;?php
class Test extends NCore_PageTest
{
    public function setUp()
    {
        // method called before each test method is run
    }
    public function tearDown()
    {
        // method called after each test method is run
    }

EOD;

        $_GET['type'] = 'GET';
        $_POST['type'] = 'POST';
        $_COOKIE['type'] = 'COOKIE';
        $_SESSION['type'] = 'SESSION';
		$page->init();
        $pipes = $page->getAllPipes();
        $actionPipes = array();
        $standardPipes = array();


        foreach ($pipes as $key=>$value)
        {
            if ($value instanceof NCore_ActionPipe)
            {
                $actionPipes[$key] = $value;
            }
            else
            {
                $standardPipes[$key] = $value;
            }
        }

        foreach ($actionPipes as $key=>$value)
        {
            foreach ($value->getActions() as $action)
            {
                $templateCode .= "    public function test".ucfirst($action).ucfirst($key)."()\n    {\n";
                
                foreach ($page->getPortGroup($action) as $port)
                {
                    $ga = $page->getPort($port)->getGlobalArray();
					$gaName = $ga['type'];
                    $templateCode .= "        // {$page->getPort($port)->getErrorMsg()}\n";
                    $templateCode .= "        \$_{$gaName}['$port'] = REPLACE_WITH_VALUE;\n\n";
                }

                $templateCode .= "        // builds page using current GPCS variables, stores markup for testing, and returns reference for use\n";
                $templateCode .= "        \$page = \$this->buildPage();\n\n";
                $templateCode .= "        //\$this->assertTrue(BOOLEAN);\n";
                $templateCode .= "        //\$this->assertFalse(BOOLEAN);\n";
                $templateCode .= "        //\$this->assertEqual(\$value1, \$value2);\n";
                $templateCode .= "        //\$this->assertMarkup(\"String searched for within markup\");\n";
                $templateCode .= "        //\$this->assertPipeMarkup('$key', \"String searched for within markup\");\n";
                $templateCode .= "        //\$this->assertPipeDataset('$key', new NCore_Dataset()):\n";
                $templateCode .= "    }\n";
            }
        }

        foreach ($standardPipes as $key=>$value)
        {
            $templateCode .= "    public function test".ucfirst($key)."()\n    {\n";
            
            foreach ($page->getPortGroup($value->getRequiredPortGroup()) as $port)
            {
                $ga = $page->getPort($port)->getGlobalArray();
                $gaName = $ga['type'];
                $templateCode .= "        // {$page->getPort($port)->getErrorMsg()}\n";
                $templateCode .= "        \$_{$gaName}['$port'] = REPLACE_WITH_VALUE;\n\n";
            }

            $templateCode .= "        // builds page using current GPCS variables, stores markup for testing, and returns reference for use\n";
            $templateCode .= "        \$page = \$this->buildPage();\n\n";
            $templateCode .= "        //\$this->assertTrue(BOOLEAN);\n";
            $templateCode .= "        //\$this->assertFalse(BOOLEAN);\n";
            $templateCode .= "        //\$this->assertEqual(\$value1, \$value2);\n";
            $templateCode .= "        //\$this->assertMarkup(\"String searched for within markup\");\n";
            $templateCode .= "        //\$this->assertPipeMarkup('$key', \"String searched for within markup\");\n";
            $templateCode .= "    }\n";
        }

        $templateCode .= "}\n?&gt;";

        $pageMarkup = <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Nephtali Page Test Template</title>
{$this->getStyleSheet()}
</head>

<body>
<div id="container">
<h1>Nephtali Page Test Template</h1>
<form>
    <textarea  style="width:700px; height:800px;" >
$templateCode
    </textarea>
</form>
</div>
</body>
</html>
EOD;

        return $pageMarkup;
    }

    public function setMarkup($markup)
    {
        $this->markup = $markup;
    }

    public function process()
    {
        if (!isset($_SESSION)) session_start();

        if (get_class($this) == 'NCore_PageTest')
		{
            return $this->createTestTemplate(new Page());
		}

        $this->results .= "<h1>Page Test Results</h1>\n";

        // cycle through each of the tests and perform, then save markup results

        foreach ($this->getMethods() as $methodName)
        {
            if ($this->hasTestPrefix($methodName))
            {
                $this->results .= "<h2>$methodName Results</h2>\n<ul>";
                $this->setUp();

                try
                {
                    $this->$methodName();
                }
                catch (Exception $e)
                {
                    $this->failedTestsCount++;
                    $this->results .= "<li class=\"failed\"><h3>Unhandled Exception</h3>\n<p><strong>Message:</strong> {$e->getMessage()}</p><p>Some of the tests within this method may not have been run do to the unhandled exception.</p></li>";
                }

                $this->tearDown();
                $this->page = NULL;
                $this->results .= "</ul>";
            }
        }

        $template = <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Nephtali Page Test Results</title>
{$this->getStyleSheet()}
</head>

<body>
<div id="container">
<p id="failed_tests" style="display:none">{$this->getFailedTestsCount()}</p>
{$this->results}
</div>
</body>
</html>
EOD;
        return $template;
    }

    public function setUp()
    {
        // hook for subclasses
    }

    public function tearDown()
    {
        // hook for subclasses
    }

    public function getPage()
    {
        return $this->page;
    }

    public function buildPage()
    {
        $this->page = new Page();
        $this->page->setMarkup($this->markup);
        $this->pageMarkup = $this->page->process();
        return $this->page;
    }

    public function assertFalse($bool)
    {
        if (!$bool)
        {
             $this->results .= '<li class="passed"><h3>AssertFalse passed</h3></li>';
        }
        else
        {
            $this->failedTestsCount++;
            $this->results .= '<li class="failed"><h3>AssertFalse failed</h3></li>';
        }
    }

    public function assertTrue($bool)
    {
        if ($bool)
        {
            $this->results .= '<li class="passed"><h3>AssertTrue passed</h3></li>';
        }
        else
        {
            $this->failedTestsCount++;
            $this->results .= '<li class="failed"><h3>AssertTrue failed</h3></li>';
        }
    }

    public function assertEqual($value1, $value2)
    {
        if($value1 == $value2)
        {
            $this->results .= '<li class="passed"><h3>AssertEqual passed</h3></li>';
        }
        else
        {
            $this->failedTestsCount++;
            $this->results .= '<li class="failed"><h3>AssertEqual failed</h3>';
            $encodedMarkup = htmlspecialchars($value1, ENT_QUOTES, 'UTF-8');
            $this->results .= "<dl><dt>Value 1</dt><dd><form><div><input value=\"$encodedMarkup\" /></div></form></dd>";
            $encodedMarkup = htmlspecialchars($value2, ENT_QUOTES, 'UTF-8');
            $this->results .= "<dt>Value 2</dt><dd><form><div><input value=\"$encodedMarkup\" /></div></form></dd></dl></li>";
        }
    }

    public function assertMarkup($string)
    {
        if (false !== strpos($this->page->getMarkup(),$string))
        {
            $this->results .= '<li class="passed"><h3>AssertMarkup passed.</h3></li>';
        }
        else
        {
            $this->failedTestsCount++;
            $this->results .= "<li class=\"failed\"><h3>AssertMarkup failed.</h3>\n";
            $encodedMarkup = htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
            $this->results .= "<dl>\n<dt>Expected result</dt><dd><form><div><textarea rows='4' cols='60'>$encodedMarkup</textarea></div></form></dd>\n";
            $encodedMarkup = htmlspecialchars($this->page->getMarkup(), ENT_QUOTES, 'UTF-8');
            $this->results .= "<dt>Actual result</dt>\n<dd><form><div><textarea rows='4' cols='60'>$encodedMarkup</textarea></div></form></dd>\n</dl>\n</li>";
       }
    }

    public function assertPipeMarkup($pipeName, $string)
    {
        if (false !== strpos($this->page->getPipe($pipeName)->getMarkup(),$string))
        {
            $this->results .= '<li class="passed"><h3>AssertPipeMarkup passed.</h3></li>';
        }
        else
        {
            $this->failedTestsCount++;
            $this->results .= "<li class=\"failed\"><h3>AssertPipeMarkup failed.</h3>\n";
            $encodedMarkup = htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
            $this->results .= "<dl>\n<dt>Expected result</dt><dd><form><div><textarea rows='4' cols='60'>$encodedMarkup</textarea></div></form></dd>\n";
            $encodedMarkup = htmlspecialchars($this->page->getPipe($pipeName)->getMarkup(), ENT_QUOTES, 'UTF-8');
            $this->results .= "<dt>Actual result</dt>\n<dd><form><div><textarea rows='4' cols='60'>$encodedMarkup</textarea></div></form></dd>\n</dl>\n</li>";
       }
    }

    public function getFailedTestsCount()
    {
        return $this->failedTestsCount;
    }

    protected function resetGlobals()
    {
        foreach ($_GET as $key=>$value)
        {
            unset($_GET[$key]);
        }

        foreach ($_POST as $key=>$value)
        {
            unset($_POST[$key]);
        }

        foreach ($_COOKIE as $key=>$value)
        {
            unset($_COOKIE[$key]);
        }

        foreach ($_SESSION as $key=>$value)
        {
            unset($_SESSION[$key]);
        }
    }

    protected function getMethods()
    {
        if (count($this->methods) < 1)
        {
            return $this->methods = get_class_methods(get_class($this));
        }
        else
        {
            return $this->methods;
        }
    }

    protected function getStyleSheet()
    {
        return $styles = <<<EOD
    <style type="text/css">
        html,body{background-color:#EEEEEE; font-size:small;}
        h1{150%; padding-top:10px;}
        h2{140%;}
        h3{130%;}
        #container{width:760px; margin:0 auto; background-color:#ffffff; border:1px solid #dddddd;}
        #container h1, #container h2, #container h3, #container h4, #container p, #container ul, #container dl, #container ol, #container form{margin-left:5px; margin-right:5px;}
        ul{padding:0;}
        li{padding:3px; margin:3px; list-style:none;}
        li.passed{background-color:#9C9;}
        li.failed{background-color:#C99;}
        dt{font-weight:bold; margin-top:10px;}
        dd{margin-left:20px; padding-left:0;}
    </style>
EOD;

    }

	protected function hasTestPrefix($string)
    {
		$valid = false;

		if (substr($string, 0, 4) == 'test')
		{
			$valid = true;
		}

		return $valid;
	}
}

?>
